const http = require('node:http')
const { AsyncLocalStorage } = require('node:async_hooks')
const EventEmitter = require('node:events')

class MyEmitter extends EventEmitter {}
const emitter = new MyEmitter()
const asyncLocalStorage = new AsyncLocalStorage()
function logWithId(msg) {
  const id = asyncLocalStorage.getStore()
  // console.log('id:', id)
  console.log(`${id !== undefined ? id : '-'}:`, msg)
}

let idSeq = 0
http
  .createServer((req, res) => {
    asyncLocalStorage.run(idSeq++, () => {
      logWithId('start')
      // Imagine any chain of async operations here
      setImmediate(() => {
        logWithId('finish')
        res.end()
      })
    })
  })
  .listen(8081)

const store = { id: 1 }
emitter.on('my-event', () => {
  asyncLocalStorage.enterWith(store)
})
emitter.on('my-event', () => {
  asyncLocalStorage.getStore() // Returns the same object
})
console.log(asyncLocalStorage.getStore()) // Returns undefined
emitter.emit('my-event')
console.log(asyncLocalStorage.getStore()) // Returns the same object

setTimeout(() => {
  http.get('http://localhost:8081')
  http.get('http://localhost:8081')
}, 500)
setTimeout(() => {
  console.log(asyncLocalStorage.getStore()) // Returns the same object
}, 1000)

// Prints:
//   0: start
//   1: start
//   0: finish
//   1: finish
